package com.dc.docs._888_面试.concurrent._6_queue;

import cn.hutool.core.util.RandomUtil;

import java.util.Objects;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Description: 阻塞队列版 生产者—消费者模式
 *
 * @author: gdc
 * @date: 2021/6/16
 * @version 1.0
 */
public class ProductConsumer_BlockQueueDemo {

    public static void main(String[] args) throws InterruptedException {
        MyResource myResource = new MyResource(new SynchronousQueue<>());
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + ", 生产线程启动");
            try {
                myResource.product();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "AA").start();

        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + ", 消费线程启动");
            try {
                myResource.consume();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "BB").start();

        TimeUnit.SECONDS.sleep(20);

        System.out.println("20秒钟时间到，main线程叫停，活动结束");
        myResource.stop();
    }
}


class MyResource{

    private volatile boolean FLAG = true;

    private AtomicInteger num = new AtomicInteger();

    /**
     * 阻塞队列
     */
    private BlockingQueue<Integer> queue;

    public MyResource(BlockingQueue<Integer> queue) {
        this.queue = queue;
        System.out.println(queue.getClass().getName());
    }

    /**
     * 生产数据
     */
    public void product() throws InterruptedException {
        while (FLAG) {
            int data = num.incrementAndGet();
            boolean offerRes = queue.offer(data, 2, TimeUnit.SECONDS);
            if (offerRes) {
                System.out.println(Thread.currentThread().getName() + "插入队列成功，数据为：" + data);
            } else {
                System.out.println(Thread.currentThread().getName() + "插入队列失败，数据为：" + data);
            }
            TimeUnit.SECONDS.sleep(RandomUtil.randomInt(1, 3));
        }

        System.out.println(Thread.currentThread().getName() + "生产动作结束，FLAG = false");
    }

    /**
     * 消费数据
     */
    public void consume() throws InterruptedException {
        while (FLAG) {
            Integer pollRes = queue.poll(2, TimeUnit.SECONDS);
            if (Objects.isNull(pollRes)) {
                FLAG = false;
                System.out.println(Thread.currentThread().getName() + ", 超过2s钟没有取到蛋糕，消费队列退出");
                return;
            } else {
                System.out.println(Thread.currentThread().getName() + "消费队列，消费成功，获取数据为：" + pollRes);
            }

            TimeUnit.SECONDS.sleep(RandomUtil.randomInt(1, 3));
        }

        System.out.println(Thread.currentThread().getName() + "消费动作结束，FLAG = false");
    }

    /**
     * 关闭服务
     */
    public void stop() {
        this.FLAG = false;
    }
}
